package com.chagee.store.operation.server.service.biz;

import cn.hutool.core.net.URLEncodeUtil;
import com.alibaba.fastjson.JSON;
import com.chagee.personnel.api.event.response.*;
import com.chagee.store.operation.api.enums.OrderAppealStatusEnum;
import com.chagee.store.operation.common.annotation.FiledDesc;
import com.chagee.store.operation.common.constant.CommonConstant;
import com.chagee.store.operation.common.constant.FeiShuMessageConstant;
import com.chagee.store.operation.common.enums.LarkMessageReceiveEnum;
import com.chagee.store.operation.common.enums.LarkMessageTypeEnum;
import com.chagee.store.operation.common.exception.BizErrorCode;
import com.chagee.store.operation.common.exception.BizException;
import com.chagee.store.operation.server.config.LarkMessageConfig;
import com.chagee.store.operation.server.model.info.MessageInfo;
import com.chagee.store.operation.server.entity.AppealReviewerConfigurationDO;
import com.chagee.store.operation.server.entity.StoreDetailDO;
import com.chagee.store.operation.server.event.service.AppealReviewerConfigurationBaseService;
import com.chagee.store.operation.server.model.bo.*;
import com.chagee.store.operation.server.model.info.LarkMessageInfo;
import com.chagee.store.operation.server.model.response.UmuUserResponse;
import com.chagee.store.operation.server.service.base.StoreDetailBaseService;
import com.chagee.store.operation.server.service.third.UmuThirdService;
import com.chagee.storeManagement.api.event.bo.StoreBaseInfoBO;
import com.chagee.storeManagement.api.event.request.BaseRequest;
import com.google.common.collect.Lists;
import com.lark.oapi.Client;
import com.lark.oapi.service.contact.v3.model.BatchGetIdUserReq;
import com.lark.oapi.service.contact.v3.model.BatchGetIdUserReqBody;
import com.lark.oapi.service.contact.v3.model.BatchGetIdUserResp;
import com.lark.oapi.service.contact.v3.model.UserContactInfo;
import com.lark.oapi.service.im.v1.model.CreateMessageReq;
import com.lark.oapi.service.im.v1.model.CreateMessageReqBody;
import com.lark.oapi.service.im.v1.model.CreateMessageResp;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.text.MessageFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author : yzq
 * @date 2024/07/02
 */

@Service
@Slf4j
public class FeiShuMessageBizService {

	@Resource
	private PersonalBizService personalBizService;
	@Resource
	private LarkMessageConfig larkMessageConfig;
	@Resource
	private ThirdPartyService thirdPartyService;
	@Resource
	private AppealReviewerConfigurationBaseService reviewerBaseService;

	@Resource
	private StoreDetailBaseService storeDetailBaseService;

	@Resource
	private UmuThirdService umuThirdService;

	private static final String TO_PROCESS = "去处理";


	// 飞书消息可发送开关
	@Value("${lark.send.flag:false}")
	private boolean sendLarkMessageFlag;

	// 飞书消息接收人白名单开关
	@Value("${lark.send.receiveWhitelist.flag:false}")
	private boolean sendLarkMessageWhiteFlag;

	// 飞书消息接收人白名单
	@Value("${lark.send.receiveWhitelist.receivers:false}")
	private List<String> sendLarkMessageWhiteReceivers;

	@Value("${lark.send.roleAlias:}")
	private String roleAlias;

	@Value("${settlement.refuseNoticeRole:}")
	private String refuseNoticeRole;

	@Value("${lark.message.domain}")
	private String domain;

	@Value("${lark.message.dynamicDomain}")
	private String dynamicDomain;

	@Value("${lark.message.appId}")
	private String appId;

	@Value("${lark.message.kungfuDomain}")
	private String kungfuDomain;

	@Value("${lark.message.kungfuLinkUrl}")
	private String kungfuLinkUrl;

	public boolean sendMessage(LarkMessageInfo message) {
		String type = message.getType();
		String storeNo = message.getStoreNo();
		LarkMessageTypeEnum byType = LarkMessageTypeEnum.getByType(type);
		MessageInfo messageInfo = larkMessageConfig.getByType(type);
		if (Objects.isNull(messageInfo) || Objects.isNull(byType)) {
			log.info("send lark message fail. error message type:{}", type);
			return false;
		}
		BaseRequest req = new BaseRequest();
		req.setStoreNo(storeNo);

		StoreBaseInfoBO storeDO = thirdPartyService.queryStoreInfo(req);
		log.info("FeiShuMessageBizService_query_store_response:{}", JSON.toJSONString(storeDO));
		if (Objects.isNull(storeDO)) {
			log.info("FeiShuMessageBizService_thirdPartyService#queryStoreInfo_does_not_exist，error storeNo:{}", storeNo);
			return false;
		}
		message.setStoreName(storeDO.getStoreName());

		//消息标题
		String messageTitle = buildMessageTitle(byType, message);
		message.setTitle(messageTitle);

		//手机号
		List<String> phones = getPhone(storeDO,type);
		log.info("triparty_query_phone_result:{} by taskType :{} and storeNo:{}", JSON.toJSONString(phones), type, storeNo);

		//消息内容参数
		List<String> messageParams = buildMessageArgs(type, message);
		message.setMessageParams(messageParams);

		// 链接
		fillMessageInfo(messageInfo, message);

		if (!CollectionUtils.isEmpty(phones)) {
			// 飞书消息是打开状态
			if (Boolean.FALSE.equals(sendLarkMessageFlag)) {
				log.info("lark_send_message_about_info, larkFlag [{}] current storeNo [{}] ", sendLarkMessageFlag, storeNo);
				return true;
			}
			if (Boolean.TRUE.equals(sendLarkMessageWhiteFlag)){
				phones = sendLarkMessageWhiteReceivers;
			}
			for (String phone : phones) {
				log.info("send lark message:{}",phone);
				try {
					sendFeiShuMsg(messageInfo, phone, message);
				} catch (Exception e) {
					log.error("手机号{}发送飞书消息失败:", phone, e);
					continue;
				}
			}
		}
		return true;
	}

	// 获取接收者手机号
	private List<String> getPhone(StoreBaseInfoBO storeDO,String type) {
		ArrayList<String> list = new ArrayList<>();

		LarkMessageTypeEnum larkMessageTypeEnum = LarkMessageTypeEnum.getByType(type);
		if (Objects.isNull(larkMessageTypeEnum)) {
			return list;
		}

		LarkMessageReceiveEnum byType = LarkMessageReceiveEnum.getByType(larkMessageTypeEnum.getReceive());
		if (Objects.isNull(byType)) {
			log.info("未知的消息接收对象，larkMessageTypeEnum：{}", larkMessageTypeEnum.getReceive());
			return list;
		}

		switch (byType){
			case START_APPEAL:
				//子公司申诉审核人>子公司三方打烊项目负责人>子公司运营总>
				//子公司申诉审核人
				List<String> appealPhones = getAppealPhone(storeDO.getCompanyId());
				if (!CollectionUtils.isEmpty(appealPhones)){
					list.addAll(appealPhones);
					return list;
				}
				//子公司三方打烊项目负责人
				List<String> tripartyManagerPhones = getDirectorPhone(storeDO.getCompanyId(),roleAlias);
				if (!CollectionUtils.isEmpty(tripartyManagerPhones)){
					list.addAll(tripartyManagerPhones);
					return list;
				}

				//子公司运营总
				List<String> serverGroupDeptLeaderPhones = getServerGroupDeptLeaderPhone(storeDO.getCompanyId());
				if (!CollectionUtils.isEmpty(serverGroupDeptLeaderPhones)){
					list.addAll(serverGroupDeptLeaderPhones);
					return list;
				}
				break;
			case APPEAL_SUCCESS:
				//子公司三方打烊项目负责人 + 店长 + 店助
				//子公司三方打烊项目负责人
				List<String> managerPhones = getDirectorPhone(storeDO.getCompanyId(),roleAlias);
				if (!CollectionUtils.isEmpty(managerPhones)){
					list.addAll(managerPhones);
				}

				//店长
				List<FindLenderByStoreNoResp> lenderList = personalBizService.getLeaderInfoByStoreNo(storeDO.getStoreNo(),CommonConstant.STORE_OWNER);
				log.info("FeiShuMessageBizService_getPhone#getLeaderInfoByStoreNo:{}店长信息{}",storeDO.getStoreNo(), JSON.toJSON(lenderList));
				if (!CollectionUtils.isEmpty(lenderList)){
					for (FindLenderByStoreNoResp lenderByStoreNoResp : lenderList) {
						list.add(lenderByStoreNoResp.getPhone());
					}
				}

				//店助
				List<FindLenderByStoreNoResp> lenderAssistantList = personalBizService.getLeaderInfoByStoreNo(storeDO.getStoreNo(),CommonConstant.STORE_OWNER_ASSISTANT);
				log.info("FeiShuMessageBizService_getPhone#getLeaderAssistantInfoByStoreNo:{}店助信息{}",storeDO.getStoreNo(), JSON.toJSON(lenderAssistantList));
				if (!CollectionUtils.isEmpty(lenderAssistantList)){
					for (FindLenderByStoreNoResp lenderByStoreNoResp : lenderAssistantList) {
						list.add(lenderByStoreNoResp.getPhone());
					}
				}

				break;
			case EXPIRED_APPEAL:
				//子公司申诉审核人
				List<String> appealList = getAppealPhone(storeDO.getCompanyId());
				if (!CollectionUtils.isEmpty(appealList)){
					list.addAll(appealList);
				}
				break;
			case HANDLE_APPEAL:
				//子公司三方打烊项目负责人
				List<String> managerPhones1 = getDirectorPhone(storeDO.getCompanyId(),roleAlias);
				if (!CollectionUtils.isEmpty(managerPhones1)){
					list.addAll(managerPhones1);
				}

				//店长
				List<FindLenderByStoreNoResp> lenderList1 = personalBizService.getLeaderInfoByStoreNo(storeDO.getStoreNo(),CommonConstant.STORE_OWNER);
				log.info("FeiShuMessageBizService_getPhone_getLeaderInfoByStoreNo:{}店长信息{}",storeDO.getStoreNo(), JSON.toJSON(lenderList1));
				if (!CollectionUtils.isEmpty(lenderList1)){
					for (FindLenderByStoreNoResp lenderByStoreNoResp : lenderList1) {
						list.add(lenderByStoreNoResp.getPhone());
					}
				}
				break;

			case ORDER_TAKING_NOTICE:
				//子公司申诉审核人
				List<String> orderTakingNoticelist = getAppealPhone(storeDO.getCompanyId());
				if (!CollectionUtils.isEmpty(orderTakingNoticelist)){
					list.addAll(orderTakingNoticelist);
				}
				break;
			case NIGHT_SWEEP:
				//三方打烊项目组负责人
				List<UserOfRolePageRequestResp> nightSweep = personalBizService.getUserOfRolePage(refuseNoticeRole);
				if (!CollectionUtils.isEmpty(nightSweep)){
					for (UserOfRolePageRequestResp user : nightSweep) {
						list.add(user.getPhone());
					}
				}
				break;
			case SETTLEMENT_SUBMIT_INVOICE:
				//门店店长/加盟商/门店负责人
				//店长
				List<FindLenderByStoreNoResp> lenders = personalBizService.getLeaderInfoByStoreNo(storeDO.getStoreNo(),CommonConstant.STORE_OWNER);
				log.info("FeiShuMessageBizService_getPhone#getLeaderInfoByStoreNo:{}店长信息{}",storeDO.getStoreNo(), JSON.toJSON(lenders));
				if (!CollectionUtils.isEmpty(lenders)){
					for (FindLenderByStoreNoResp lenderByStoreNoResp : lenders) {
						list.add(lenderByStoreNoResp.getPhone());
					}
				}
				//加盟商
				StoreDetailDO storeDetailDO = storeDetailBaseService.queryDetailByStoreId(storeDO.getId());
				if (StringUtils.isNotBlank(storeDetailDO.getPhone())) {
					list.add(storeDetailDO.getPhone());
				}
				//门店负责人
				UmuUserResponse response = umuThirdService.getManagerByStoreCode(storeDO.getStoreNo());
				if (Objects.nonNull(response) && StringUtils.isNotBlank(response.getPhone())) {
					list.add(response.getPhone());
				}
				break;

		}
		return list;
	}

	//消息标题
	public String buildMessageTitle(LarkMessageTypeEnum typeEnum, LarkMessageInfo message) {
		String messageTitle = typeEnum.getMessageTitle();
		switch (typeEnum){
			case expired_appeal:
			case specialOrderAppealRejected:
				List<String> list = Lists.newArrayList(message.getStoreName());
				messageTitle = MessageFormat.format(messageTitle, list.toArray(new String[list.size()]));
				break;
			case handle_appeal:
				String appealResult = message.getAppealResult();
				List<String> list1 = Lists.newArrayList(message.getStoreName(), OrderAppealStatusEnum.queryByType(appealResult).getDesc());
				messageTitle = MessageFormat.format(messageTitle, list1.toArray(new String[list1.size()]));
				break;
			case order_appeal:
				List<String> apperlList = Lists.newArrayList(message.getStoreName());
				messageTitle = MessageFormat.format(messageTitle, apperlList.toArray(new String[apperlList.size()]));
				break;
			case handle_order_appeal:
				String handleResult = message.getAppealResult();
				List<String> list2 = Lists.newArrayList(message.getStoreName(), OrderAppealStatusEnum.queryByType(handleResult).getDesc());
				messageTitle = MessageFormat.format(messageTitle, list2.toArray(new String[list2.size()]));
				break;
		}

		return messageTitle;
	}

	private List<String> getAppealPhone(String companyId){
		List<String> appealPhone = new ArrayList<>();
		//子公司申诉审核人
		List<AppealReviewerConfigurationDO> reviewers = reviewerBaseService.queryByCompany(companyId);
		if (!CollectionUtils.isEmpty(reviewers)) {
			List<Long> reviewerIds = reviewers.stream().map(record -> Long.parseLong(record.getReveiwerId())).collect(Collectors.toList());
			//批量查询审核人信息
			List<EmployeeResp> chageeUserDetailListByUserIds = personalBizService.getChageeUserDetailListByUserIds(reviewerIds);
			log.info("FeiShuMessageBizService_getAppealPhone_getChageeUserDetailListByUserIds:{}", chageeUserDetailListByUserIds);
			appealPhone = chageeUserDetailListByUserIds.stream().map(EmployeeResp::getPhone).collect(Collectors.toList());
		}
		return appealPhone;
	}

	private List<String> getDirectorPhone(String companyId,String roleAlias){
		//子公司三方打烊项目负责人
		List<String> directorPhones = new ArrayList<>();
		List<UserOfRolePageRequestResp> users = personalBizService.getUserOfRolePage(roleAlias);
		log.info("FeiShuMessageBizService_getDirectorPhone_getUserOfRolePage:{}",users);
		for (UserOfRolePageRequestResp user : users) {
			StoreAndChildCompanyOfUserResp childCompanyOfUser = personalBizService.getChildCompanyOfUser(String.valueOf(user.getId()));
			log.info("{}:FeiShuMessageBizService_getDirectorPhone_getChildCompanyOfUser:{}",user,childCompanyOfUser);
			if (!CollectionUtils.isEmpty(childCompanyOfUser.getChildCompanyIdList()) && childCompanyOfUser.getChildCompanyIdList().contains(companyId)){
				directorPhones.add(user.getPhone());
			}
		}

		return directorPhones;
	}

	private List<String> getServerGroupDeptLeaderPhone(String companyId){
		//子公司运营总
		EmployeeResp employeeResp = personalBizService.queryServerGroupDeptLeader(companyId, "");
		log.info("FeiShuMessageBizService_getServerGroupDeptLeaderPhone_queryServerGroupDeptLeader:{}",employeeResp);
		String leaderPhone = Optional.ofNullable(employeeResp).map(EmployeeResp::getPhone).orElse("");
		if (StringUtils.isNotEmpty(leaderPhone)){
			return Lists.newArrayList(leaderPhone);
		}else{
			return Lists.newArrayList();
		}
	}

	/**
	 * 发送飞书消息
	 *
	 * @param phone   接收者手机号
	 * @param message
	 * @return 发送状态 成功 OR 失败
	 * @throws BizException exception
	 */
	private boolean sendFeiShuMsg(MessageInfo messageInfo, String phone, LarkMessageInfo message) {
		Client client = Client.newBuilder(messageInfo.getAppId(), messageInfo.getAppSecret()).build();
		String openId = getFeiShuOpenId(client, phone);

		log.info("FeiShuMessageBizService#sendFeiShuMsg_storeName [{}] messageInfo [{}] messageUrl [{}]", message.getStoreName(), messageInfo.getMessage(), messageInfo.getHref());
		return sendMessage(client, openId, message, messageInfo, message.getMessageParams().toArray(new String[message.getMessageParams().size()]));
	}

	/**
	 * 填充消息url
 	 */
	private void fillMessageInfo(MessageInfo messageInfo, LarkMessageInfo message) {
		LarkMessageTypeEnum typeEnum = LarkMessageTypeEnum.getByType(messageInfo.getType());
		if (Objects.isNull(typeEnum)) {
			log.info("fillMessageInfo: larkMessageTypeEnum is null, message type :{}", messageInfo.getType());
			return;
		}
		String href = messageInfo.getHref();
		if (StringUtils.isBlank(href)) {
			log.info("fillMessageInfo: message href is empty. messageInfo : {}", JSON.toJSONString(messageInfo));
			return;
		}
		switch (typeEnum) {
			case appealNotice:
				href = href.replace("#{workOrderNumber}", message.getWorkOrderNumber()).replace("#{storeNo}",message.getStoreNo());
				break;
			case expired_appeal:
				href = href.replace("#{workOrderNumber}", message.getWorkOrderNumber());
				break;
			case order_appeal:
				href = href.replace("#{workOrderNumber}", message.getWorkOrderNumber());
				break;
			case storeRejected:
				String format = MessageFormat.format(messageInfo.getHref(), domain, message.getSettlementNo());
				href = dynamicDomain.concat(format);
				break;
			case supplierRejected:
				String format1 = MessageFormat.format(messageInfo.getHref(), domain, message.getSettlementNo());
				href = dynamicDomain.concat(format1);
				break;
			case submitInvoice:
				href = buildUrl(message, messageInfo.getHref());
				break;
			case settlementWaitPay:
				href = buildUrl(message, messageInfo.getHref());
				break;
		}
		messageInfo.setHref(href);

	}

	private String buildUrl(LarkMessageInfo messageInfo, String href) {
		String target_url = MessageFormat.format(href, kungfuDomain, messageInfo.getStoreNo());

		String targetUrlEncode = URLEncodeUtil.encodeAll(target_url);
		log.info("lkTargetUrl_Encode:{}", targetUrlEncode);
		String h5Url = MessageFormat.format(kungfuLinkUrl, appId, targetUrlEncode);
		log.info("h5Url:{}", h5Url);
		return h5Url;
	}

	public boolean sendMessage(Client client, String receiveId, LarkMessageInfo message, MessageInfo messageInfo, Object... args) {
		LarkMessageTypeEnum typeEnum = LarkMessageTypeEnum.getByType(message.getType());
		if (Objects.isNull(typeEnum)) {
			log.info("fillMessageInfo: larkMessageTypeEnum is null, message type :{}", message.getType());
			return false;
		}

		String content = getMessageContent(message.getTitle(), MessageFormat.format(messageInfo.getMessage(), args),TO_PROCESS, messageInfo.getHref());
		switch (typeEnum) {
			case handle_appeal:
				if (OrderAppealStatusEnum.Y.getType().equals(message.getAppealResult())) {
					content = getMessageContent(message.getTitle(), MessageFormat.format(messageInfo.getMessageExt(), args),TO_PROCESS, messageInfo.getHref());
				}
				break;
			case handle_order_appeal:
				if (OrderAppealStatusEnum.Y.getType().equals(message.getAppealResult())) {
					content = getMessageContent(message.getTitle(), MessageFormat.format(messageInfo.getMessageExt(), args),TO_PROCESS, messageInfo.getHref());
				}
				break;
		}

		// 创建请求对象
		CreateMessageReq req = CreateMessageReq.newBuilder()
			.receiveIdType(FeiShuMessageConstant.RECEIVE_ID_TYPE)
			.createMessageReqBody(CreateMessageReqBody.newBuilder()
				.receiveId(receiveId)
				.msgType("interactive")
				.content(content)
				.build())
			.build();

		// 发起请求
		CreateMessageResp resp = null;
		try {
			resp = client.im().message().create(req);
		} catch (Exception e) {
			log.error("send feiShu message:{} fail.", MessageFormat.format(messageInfo.getMessage(), args),  e);
			throw new BizException(BizErrorCode.SEND_LARK_MESSAGE_FAIL);
		}

		log.info("send feiShu message:{} response data:{}, code:{}, msg:{}", MessageFormat.format(messageInfo.getMessage(), args), JSON.toJSONString(resp.getData()), resp.getCode(), resp.getMsg());

		// 业务失败
		if (resp.success()) {
			return true;
		}

		throw new BizException(resp.getMsg());
	}
	/**
	 * 构建消息通知数据
	 * @param message
	 * @return
	 */
	private List<String> buildMessageArgs(String type, LarkMessageInfo message) throws BizException {
		List<String> list = new ArrayList<>();
		LarkMessageTypeEnum messageTypeEnum = LarkMessageTypeEnum.getByType(type);
		if (Objects.isNull(messageTypeEnum)) {
			return list;
		}
		String storeName = message.getStoreName();
		switch (messageTypeEnum) {
			case appealNotice:
				list.add(storeName);
				break;
			case appealSuccessNotice:
			case taskAppealRejected:
				list.add(storeName);
				list.add(message.getOrderCreateTime());
				list.add(message.getTaskName());
				list.add(message.getHandleAppealReason());
				break;
			case expired_appeal:
				list.add(storeName);
				break;
			case handle_appeal:
				list.add(storeName);
				list.add(OrderAppealStatusEnum.queryByType(message.getAppealResult()).getDesc());
				//通过显示评分结果
				if (OrderAppealStatusEnum.Y.getType().equals(message.getAppealResult())) {
					list.add(message.getOrderAcceptanceStatus());
				}
				list.add(message.getHandleAppealReason());
				break;
			case order_appeal:
				list.add(storeName);
				break;
			case handle_order_appeal:
				list.add(storeName);
				list.add(OrderAppealStatusEnum.queryByType(message.getAppealResult()).getDesc());
				//通过显示评分结果
				if (OrderAppealStatusEnum.Y.getType().equals(message.getAppealResult())) {
					list.add(message.getOrderAcceptanceStatus());
				}
				list.add(message.getHandleAppealReason());
				break;
			case storeRejected:
				list.add(storeName);
				list.add(message.getSupplierName());
				break;
			case supplierRejected:
				list.add(storeName);
				list.add(message.getSupplierName());
				break;
			case submitInvoice:
				list.add(storeName);
				break;
			case settlementWaitPay:
				list.add(storeName);
				break;
			case orderAppealRejected:
			case specialOrderAppealRejected:
				list.add(storeName);
				list.add(message.getOrderCreateTime());
				list.add(message.getHandleAppealReason());
				break;
		}

		return list;
	}

	/**
	 * 创建消息content
	 * @param title
	 * @param content
	 * @param buttonMsg
	 * @param url
	 * @return
	 */
	private String getMessageContent(String title, String content, String buttonMsg, String url) {
		StringBuilder builder = new StringBuilder();
		builder.append("{"+
			"\"config\": {"+
			"\"wide_screen_mode\": true" +
			"}," +
			"\"elements\": [{"+
			"\"tag\": \"div\","+
			"\"text\": {" +
			"\"content\": \""+ content +"\"," +
			"\"tag\": \"lark_md\""+
			"}" +
			"}");
		if (StringUtils.isNotBlank(url)) {
			builder.append(", {" +
				"\"actions\": [{" +
				"\"tag\": \"button\"," +
				"\"text\": {" +
				"\"content\": \"" + buttonMsg + "\"," +
				"\"tag\": \"plain_text\"" +
				"}," +
				"\"type\": \"primary\"," +
				"\"url\": \"" + url + "\"" +
				"}]," +
				"\"tag\": \"action\"" +
				"}");
		}
		builder.append("]," +
			"\"header\": {"+
			"\"template\": \"turquoise\"," +
			"\"title\": {" +
			"\"content\": \""+ title +"\"," +
			"\"tag\": \"plain_text\"}}}");
		return builder.toString();
	}

	/**
	 * 通过手机号获取用户openId
	 * @param phone 消息接收人手机号
	 * @return openId
	 */
	private String getFeiShuOpenId(Client client, String phone) {
		// 创建请求对象
		BatchGetIdUserReq req = BatchGetIdUserReq.newBuilder()
			.userIdType(FeiShuMessageConstant.RECEIVE_ID_TYPE)
			.batchGetIdUserReqBody(BatchGetIdUserReqBody.newBuilder()
				.mobiles(new String[] {
					phone
				})
				.build())
			.build();

		// 发起请求
		BatchGetIdUserResp resp = null;
		try {
			resp = client.contact().user().batchGetId(req);
		} catch (Exception e) {
			log.error("query openId from feiShu fail. phone:{}", phone,  e);
			throw new BizException(BizErrorCode.GET_LARK_OPENID_FAIL);
		}

		log.info("query openId from feiShu response data:{}, phone:{}, code:{}, msg:{}", JSON.toJSONString(resp.getData()), phone, resp.getCode(), resp.getMsg());
		// 处理服务端错误
		if(!resp.success()) {
			throw new BizException(resp.getMsg());
		}

		UserContactInfo[] userList = resp.getData().getUserList();
		UserContactInfo userContactInfo = userList[0];
		if (Objects.nonNull(userContactInfo) && StringUtils.isNotBlank(userContactInfo.getUserId())) {
			return userContactInfo.getUserId();
		}

		throw new BizException("openId is empty");
	}

	public boolean sendMessage2(LarkMessageInfo message) {
		String type = message.getType();
		String storeNo = message.getStoreNo();
		LarkMessageTypeEnum byType = LarkMessageTypeEnum.getByType(type);
		MessageInfo messageInfo = larkMessageConfig.getByType(type);
		if (Objects.isNull(messageInfo) || Objects.isNull(byType)) {
			log.info("send lark message fail. error message type:{}", type);
			return false;
		}
		BaseRequest req = new BaseRequest();
		req.setStoreNo(storeNo);

		StoreBaseInfoBO storeDO = thirdPartyService.queryStoreInfo(req);
		log.info("FeiShuMessageBizService_query_store_response:{}", JSON.toJSONString(storeDO));
		if (Objects.isNull(storeDO)) {
			log.info("FeiShuMessageBizService_thirdPartyService#queryStoreInfo_does_not_exist，error storeNo:{}", storeNo);
			return false;
		}

		//标题
		String messageTitle = buildMessageTitle(byType, message);
		//文案
		String copyWriting = buildCopyWriting(messageInfo, message);
		List<String> phones = getPhone(storeDO, type);

		log.info("FeiShu_sendMsg_phone_result:{} by taskType :{} and storeNo:{}", JSON.toJSONString(phones), type, storeNo);

		if (!CollectionUtils.isEmpty(phones)) {
			// 飞书消息是打开状态
			if (Boolean.FALSE.equals(sendLarkMessageFlag)) {
				log.info("lark_send_message_about_info, larkFlag [{}] current storeNo [{}] ", sendLarkMessageFlag, storeNo);
				return true;
			}
			if (Boolean.TRUE.equals(sendLarkMessageWhiteFlag)){
				phones = sendLarkMessageWhiteReceivers;
			}
			for (String phone : phones) {
				log.info("send lark message:{}",phone);
				try {
					sendFeiShuMsg2(messageInfo, messageTitle, phone, copyWriting, message.getColumns(), message.getRows());
				} catch (Exception e) {
					log.error("手机号{}发送飞书消息失败:", phone, e);
					continue;
				}
			}
		}
		return true;
	}

	/**
	 * @param messageInfo 配置信息
	 * @param title 标题
	 * @param phone 手机号
	 * @param copywriting  文案
	 * @param columns 表头
	 * @param rows 数据
	 * @return
	 */
	private boolean sendFeiShuMsg2(MessageInfo messageInfo, String title, String phone, String copywriting, List<Object> columns, List<Object> rows) {
		Client client = Client.newBuilder(messageInfo.getAppId(), messageInfo.getAppSecret()).build();
		String openId = getFeiShuOpenId(client, phone);
		log.info("FeiShuMessageBizService#sendFeiShuMsg_storeName [{}] messageInfo [{}] messageUrl [{}]", title, messageInfo.getMessage(), messageInfo.getHref());
		String content = buildContent(title, copywriting, columns, rows);
		return sendMsg(client, openId, content);
	}

	public String buildContent(String title, String copywriting, List<Object> columns, List<Object> rows) {
		FeiShuMsgContentBO msgContent = new FeiShuMsgContentBO();

		msgContent.setConfig(new FeiShuConfigBO().setWide_screen_mode(true));
		//标题
		msgContent.setHeader(new FeiShuHeaderBO().setTitle(new FeiShuTitleBO().setContent(title)));

		List<Object> elementsList = new ArrayList<>();
		//推送文案
		if (StringUtils.isNotBlank(copywriting)) {
			FeiShuCopywritingBO feiShuCopywritingBO = new FeiShuCopywritingBO().setText(new FeiShuCopywritingBO.CopywritingInfo().setContent(copywriting));
			elementsList.add(feiShuCopywritingBO);
		}

		if (!CollectionUtils.isEmpty(columns) && !CollectionUtils.isEmpty(rows)) {
			FeiShuTableBO feiShuTableBO = new FeiShuTableBO().setColumns(columns).setRows(rows);
			elementsList.add(feiShuTableBO);
		}

		msgContent.setElements(elementsList);
		String content = JSON.toJSONString(msgContent);
		return content;
	}

	public String buildCopyWriting(MessageInfo messageInfo, LarkMessageInfo info) {
		String message = messageInfo.getMessage();
		List<String> list = Collections.singletonList(info.getCompanyName());
		return MessageFormat.format(message, list.toArray(new String[list.size()]));
	}

	public boolean sendMsg(Client client, String receiveId, String content) {
		// 创建请求对象
		CreateMessageReq req = CreateMessageReq.newBuilder()
			.receiveIdType(FeiShuMessageConstant.RECEIVE_ID_TYPE)
			.createMessageReqBody(CreateMessageReqBody.newBuilder()
				.receiveId(receiveId)
				.msgType("interactive")
				.content(content)
				.build())
			.build();

		// 发起请求
		CreateMessageResp resp = null;
		try {
			resp = client.im().message().create(req);
		} catch (Exception e) {
			log.error("send feiShu message:{} fail.", content,  e);
			throw new BizException(BizErrorCode.SEND_LARK_MESSAGE_FAIL);
		}

		log.info("send feiShu message:{} response data:{}, code:{}, msg:{}", content, JSON.toJSONString(resp.getData()), resp.getCode(), resp.getMsg());

		// 业务失败
		if (resp.success()) {
			return true;
		}
		throw new BizException(resp.getMsg());
	}

	public List<Object> buildColumns(Class data) {
		List<Object> columnsList = new ArrayList<>();

		Field[] fields = data.getDeclaredFields();
		for (Field field : fields) {

			FiledDesc annotation = field.getAnnotation(FiledDesc.class);
			if (Objects.isNull(annotation)) {
				continue;
			}
			field.setAccessible(true);

			String name = field.getName();
			//注解
			String value = annotation.value();

			FeiShuColumnsBO feiShuColumnsBO = new FeiShuColumnsBO().setName(name).setDisplay_name(value);
			columnsList.add(feiShuColumnsBO);
		}
		return columnsList;
	}


}
